﻿/*============================================================================

* File Name : Vector4.cpp                         Ver : 1.00  Date : 2009-3-20
*
* Description :
*
*       4Dベクトル計算　ソース
*
* Author : 土田　悠貴.
*============================================================================*/
#include "Vector4.h"
#include "Vector3.h"
#include "Vector2.h"
#include "Matrix3.h"
#include "Matrix4.h"
#include "Math.h"

namespace tglib
{

/*===========================================================================*/
/**
 * コンストラクタ．
 */
Vector4::Vector4() : x( 0.0f ), y( 0.0f ), z( 0.0f ), w( 0.0f )
{}

/*===========================================================================*/
/**
 * コンストラクタ．
 *
 * @param [in] X　x座標．
 * @param [in] Y　y座標．
 * @param [in] Z　z座標．
 * @param [in] W　w座標．
 */
Vector4::Vector4( float X, float Y, float Z, float W ) :
	x( X ), y ( Y ), z( Z ), w( W )
{}

/*===========================================================================*/
/**
 * コンストラクタ．
 *
 * @param [in] v2　2Dベクトル．
 * @param [in] Z　 Z座標．
 * @param [in] W　 w成分．
 */
Vector4::Vector4( const Vector2& v2, float Z, float W ) : 
	x( v2.x ), y( v2.y ), z( Z ), w( W )
{}

/*===========================================================================*/
/**
 * コンストラクタ．
 *
 * @param [in] v3　3Dベクトル．
 * @param [in] W　 w成分．
 */
Vector4::Vector4( const Vector3& v3, float W ) :
	x( v3.x ), y( v3.y ), z( v3.z ), w( W )
{}

/*===========================================================================*/
/**
 * コンストラクタ．
 *
 * @param [in] p　配列のポインタ．
 */
Vector4::Vector4( const float* p ) :
	x( p[0] ), y( p[0] ), z( p[0] ), w( p[3] )
{}

/*===========================================================================*/
/**
 * 正規化．
 *
 * @return 正規化したベクトル．
 */
Vector4& Vector4::normalize()
{
	float len;

	if( ( len = length() ) != 0 ){
		(*this) /= len;
	}

	return *this;
}

/*===========================================================================*/
/**
 * 正規化したベクトルを取得する．
 *
 * @return 正規化したベクトル．
 */
Vector4 Vector4::getNormalized() const
{
	Vector4	result( *this );

	return result.normalize();
}

/*===========================================================================*/
/**
 * 長さを求める．
 *
 * @return 長さ ．
 */
float Vector4::length() const
{
	return Math::Sqrt( lengthSq() );
}

/*===========================================================================*/
/**
 * 長さを求める (２乗和のみ）．
 *
 * @return 長さ(２乗和）．
 */
float Vector4::lengthSq() const
{
	return ( x * x + y * y );
}

/*===========================================================================*/
/**
 * 距離を求める．
 *
 * @param [in]  V 4Dベクトル ．
 * @return 距離 ．
 */
float Vector4::distance( const Vector4& V ) const
{
	Vector4 result;

	result = *this - V;

	return ( result.length() );
}

/*===========================================================================*/
/**
 * 内積を求める．
 *
 * @param [in]  V 4Dベクトル ．
 * @return 内積 ．
 */
float Vector4::dot( const Vector4& V ) const
{
	return ( x * V.x + y *V.y + z * V.z + w * V.w );
}

/*===========================================================================*/
/**
 * 小さい要素を求める．
 *
 * @param [in]  V 4Dベクトル ．
 * @return 小さい要素 ．
 */
Vector4 Vector4::minimize( const Vector4& V ) const
{
	Vector4 result;

	result.x = Math::MIN( x, V.x );
	result.y = Math::MIN( y, V.y );
	result.z = Math::MIN( z, V.z );
	result.w = Math::MIN( w, V.w );

	return result;
}

/*===========================================================================*/
/**
 * 大きい要素を求める．
 *
 * @param [in]  V 4Dベクトル ．
 * @return 大きい要素 ．
 */
Vector4 Vector4::maximize( const Vector4& V ) const
{
	Vector4 result;

	result.x = Math::MAX( x, V.x );
	result.y = Math::MAX( y, V.y );
	result.z = Math::MAX( z, V.z );
	result.w = Math::MAX( w, V.w );

	return result;
}

/*=========================================================================*/
/**
 * @brief ベクトルの線形補間を行う
 * 
 * @param [in] min 最小値.
 * @param [in] max 最大値.
 * @param [in] t 補間値( 0.0f～1.0f ).
 * @return 結果のベクトル.
 */
Vector4& Vector4::lerp( const Vector4& min, const Vector4& max, float t )
{
	x = Math::LERP( t, min.x, max.x );
	y = Math::LERP( t, min.y, max.y );
	z = Math::LERP( t, min.z, max.z );
	w = Math::LERP( t, min.w, max.w );

	return *this;
}

/*===========================================================================*/
/**
 * 二次補間を行う．
 *
 * @param [in]  v1 補間要素4次元ベクトル.
 * @param [in]  v2 補間要素4次元ベクトル.
 * @param [in]  v3 補間要素4次元ベクトル.
 * @param [in]  t 補間値( 0.0f～1.0f ).
 * @return 補間した3Dベクトル ．
 */
Vector4& Vector4::quadratic(const Vector4& v1, const Vector4& v2, const Vector4& v3, float t)
{
	x = Math::QUADRATIC( t, v1.x, v2.x, v3.x );
	y = Math::QUADRATIC( t, v1.y, v2.y, v3.y );
	z = Math::QUADRATIC( t, v1.z, v2.z, v3.z );
	w = Math::QUADRATIC( t, v1.w, v2.w, v3.w );

	return	*this;
}

/*===========================================================================*/
/**
 * (+)単項演算子オーバーロード．
 *
 * @return 結果のVector4．
 */
Vector4 Vector4::operator + () const
{
	return *this;
}

/*===========================================================================*/
/**
 * (-)単項演算子オーバーロード．
 *
 * @return 結果のVector4.
 */
Vector4 Vector4::operator - () const
{
	return Vector4( -x, -y, -z, -w );
}

/*===========================================================================*/
/**
 * (+=) 演算子オーバーロード．
 * 
 * @param [in]  v Vector4．
 * @return 結果のVector4．
 */
Vector4& Vector4::operator += ( const Vector4& v )
{
	x = x + v.x;
	y = y + v.y;
	z = z + v.z;
	w = w + v.w;

	return *this;
}

/*===========================================================================*/
/**
 * (-=) 演算子オーバーロード．
 * 
 * @param [in]  v Vector4．
 * @return 結果のVector4．
 */
Vector4& Vector4::operator -= ( const Vector4& v )
{
	x = x - v.x;
	y = y - v.y;
	z = z - v.z;
	w = w - v.w;

	return *this;
}

/*===========================================================================*/
/**
 * (*=) 演算子オーバーロード．
 * 
 * @param [in]  v Vector4．
 * @return 結果のVector4．
 */
Vector4& Vector4::operator *= ( const Vector4& v )
{
	x = x * v.x;
	y = y * v.y;
	z = z * v.z;
	w = w * v.w;

	return *this;
}

/*===========================================================================*/
/**
 * (/=) 演算子オーバーロード．
 * 
 * @param [in]  v Vector4．
 * @return 結果のVector4．
 */
Vector4& Vector4::operator /= ( const Vector4& v )
{
	x = x / v.x;
	y = y / v.y;
	z = z / v.z;
	w = w / v.w;

	return *this;
}

/*===========================================================================*/
/**
 * (*=) 演算子オーバーロード．
 * 
 * @param [in]  s スカラー．
 * @return 結果のVector4．
 */
Vector4& Vector4::operator *= ( float s )
{
	x = x * s;
	y = y * s;
	z = z * s;
	w = w * s;

	return *this;
}

/*===========================================================================*/
/**
 * (/=) 演算子オーバーロード．
 * 
 * @param [in]  s スカラー．
 * @return 結果のVector4．
 */
Vector4& Vector4::operator /= ( float s )
{
	x = x / s;
	y = y / s;
	z = z / s;
	w = w / s;
	
	return *this;
}

/***  以下非メンバ関数 *******************************************************/

/*===========================================================================*/
/**
 * (+)演算子オーバーロード．
 * 
 * @param [in]  v1 Vector4．
 * @param [in]  v2 Vector4．
 * @return 結果のVector4．
 */
const Vector4 operator + ( const Vector4& v1, const Vector4& v2 )
{
	Vector4 result( v1 );

	result += v2;

	return result;
}

/*===========================================================================*/
/**
 * (-)演算子オーバーロード．
 * 
 * @param [in]  v1 Vector4．
 * @param [in]  v2 Vector4．
 * @return 結果のVector4．
 */
const Vector4 operator - ( const Vector4& v1, const Vector4& v2 )
{
	Vector4 result( v1 );

	result -= v2;

	return result;
}

/*===========================================================================*/
/**
 * (*)演算子オーバーロード．
 * 
 * @param [in]  v1 Vector4．
 * @param [in]  v2 Vector4．
 * @return 結果のVector4．
 */
const Vector4 operator * ( const Vector4& v1, const Vector4& v2 )
{
	Vector4 result( v1 );

	result *= v2;

	return result;
}

/*===========================================================================*/
/**
 * (*)演算子オーバーロード．
 * 
 * @param [in]  v Vector4．
 * @param [in]  s スカラー．
 * @return 結果のVector4．
 */
const Vector4 operator * ( const Vector4& v, const float s )
{
	Vector4 result( v );

	result *= s;

	return result;
}

/*===========================================================================*/
/**
 * (*)演算子オーバーロード．
 * 
 * @param [in]  s スカラー．
 * @param [in]  v Vector4．
 * @return 結果のVector4．
 */
const Vector4 operator * ( const float s, const Vector4& v )
{
	return v * s;
}

/*===========================================================================*/
/**
 * (/)演算子オーバーロード．
 * 
 * @param [in]  v1 Vector4．
 * @param [in]  v2 Vector4．
 * @return 結果のVector4．
 */
const Vector4 operator / ( const Vector4& v1, const Vector4& v2 )
{
	Vector4 result( v1 );

	result /= v2;

	return result;
}

/*===========================================================================*/
/**
 * (/)演算子オーバーロード．
 * 
 * @param [in]  v Vector4．
 * @param [in]  s スカラー．
 * @return 結果のVector4．
 */
const Vector4 operator / ( const Vector4& v, float s )
{
	Vector4 result( v );

	result /= s;

	return result;
}

/*===========================================================================*/
/**
 * (/)演算子オーバーロード．
 * 
 * @param [in]  s スカラー．
 * @param [in]  v Vector4．
 * @return 結果のVector4．
 */
const Vector4 operator / ( float s, const Vector4& v )
{
	return v / s;
}

/*===========================================================================*/
/**
 * (==) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector4．
 * @param [in]  v2 Vector4．
 * @return 比較結果．
 */
bool operator == ( const Vector4& v1, const Vector4& v2 )
{
	return ( v1.x == v2.x && v1.y == v2.y && v1.z == v2.z && v1.w == v2.w );
}

/*===========================================================================*/
/**
 * (!=) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector4．
 * @param [in]  v2 Vector4．
 * @return 比較結果．
 */
bool operator != ( const Vector4& v1, const Vector4& v2 )
{
	return !( v1 == v2 );
}

/*===========================================================================*/
/**
 * (<) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector4．
 * @param [in]  v2 Vector4．
 * @return 比較結果．
 */
bool operator < ( const Vector4& v1, const Vector4& v2 )
{
	if( v1.x >= v2.x )
	{
		return false;
	}
	if( v1.y >= v2.y )
	{
		return false;
	}
	if( v1.z >= v2.z )
	{
		return false;
	}
	if( v1.w >= v2.w )
	{
		return false;
	}

	return true;
}

/*===========================================================================*/
/**
 * (>) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector4．
 * @param [in]  v2 Vector4．
 * @return 比較結果．
 */
bool operator > ( const Vector4& v1, const Vector4& v2 )
{
	if( v1.x <= v2.x )
	{
		return false;
	}
	if( v1.y <= v2.y )
	{
		return false;
	}
	if( v1.z <= v2.z )
	{
		return false;
	}
	if( v1.w <= v2.w )
	{
		return false;
	}

	return true;
}

/*===========================================================================*/
/**
 * (<=) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector4．
 * @param [in]  v2 Vector4．
 * @return 比較結果．
 */
bool operator <= ( const Vector4& v1, const Vector4& v2 )
{
	if( v1.x > v2.x )
	{
		return false;
	}
	if( v1.y > v2.y )
	{
		return false;
	}
	if( v1.z > v2.z )
	{
		return false;
	}
	if( v1.w > v2.w )
	{
		return false;
	}

	return true;
}

/*===========================================================================*/
/**
 * (>=) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector4．
 * @param [in]  v2 Vector4．
 * @return 比較結果．
 */
bool operator >= ( const Vector4& v1, const Vector4& v2 )
{
	if( v1.x < v2.x )
	{
		return false;
	}
	if( v1.y < v2.y )
	{
		return false;
	}
	if( v1.z < v2.z )
	{
		return false;
	}
	if( v1.w < v2.w )
	{
		return false;
	}

	return true;
}

} // namespace tglib

/*========= End of File =====================================================*/
